#include "UARTDriverC.h"
#include "GipsyModule.h"
#include "DSP2833x_Device.h"
#include <string.h>

extern GipsyModule gipsyModule;
extern "C" void UARTDriverCInt()
{
	gipsyModule.ReadProcess();
}

// SCIC
bool UARTDriverC::Init()
{
	EALLOW;
	
	// 1. GPIO
	GpioCtrlRegs.GPBPUD.bit.GPIO62 = 0;    // Enable pull-up for GPIO62 (SCIRXDC)
	GpioCtrlRegs.GPBPUD.bit.GPIO63 = 0;	   // Enable pull-up for GPIO63 (SCITXDC)
	GpioCtrlRegs.GPBQSEL2.bit.GPIO62 = 3;  // Asynch input GPIO62 (SCIRXDC)
	GpioCtrlRegs.GPBMUX2.bit.GPIO62 = 1;   // Configure GPIO62 for SCIRXDC operation
	GpioCtrlRegs.GPBMUX2.bit.GPIO63 = 1;   // Configure GPIO63 for SCITXDC operation

    // 2. BAUD AND CONFIG
    ScicRegs.SCICCR.all =0x0007;   // 1 stop bit,  No loopback, No parity,8 char bits, async mode, idle-line protocol
	ScicRegs.SCICTL1.all =0x0003;  // enable TX, RX, internal SCICLK, Disable RX ERR, SLEEP, TXWAKE
	ScicRegs.SCICTL2.all =0x0000;
	ScicRegs.SCIHBAUD    =0x0001;  // 9600 baud @LSPCLK = 37.5MHz, switch to 0x79 for 38400
	ScicRegs.SCILBAUD    =0x00E7;
	
	// 3. FIFO
	ScicRegs.SCIFFRX.bit.RXFIFORESET = 0; // hold in reset
	ScicRegs.SCIFFRX.bit.RXFFOVRCLR=1;   // Clear Overflow flag
	ScicRegs.SCIFFTX.bit.SCIRST = 1; // enable
	ScicRegs.SCIFFTX.bit.SCIFFENA = 1; // enable Fifo
	ScicRegs.SCIFFRX.bit.RXFFINTCLR=1;	// Clear SCI Interrupt flag
	ScicRegs.SCIFFRX.bit.RXFFIENA = 1;	// enable rx fifo on match
	ScicRegs.SCIFFRX.bit.RXFFIL = 16; // level = 16 (int only when fifo is full, TODO: try to reduce to 10!)
    ScicRegs.SCIFFCT.all=0x00;
   
	ScicRegs.SCICTL1.all =0x0023;  // Relinquish SCI from Reset   
 	ScicRegs.SCIFFRX.bit.RXFIFORESET = 1; // renable fifo
 	EDIS;
 	
 	m_Buffer.clear(); // clear buffer
 	
 	
	return true;
}

void UARTDriverC::SendChar(char ch)
{
	while (ScicRegs.SCIFFTX.bit.TXFFST != 0) {}
    ScicRegs.SCITXBUF=ch;
}

void UARTDriverC::SendData(char* buffer, int length)
{
	for(int i=0; i!= length; i++)
	{
		SendChar(*buffer);
		buffer++;
	}
}

void UARTDriverC::SendData(char* buffer)
{
	SendData(buffer, strlen(buffer));
} 

bool UARTDriverC::ReadChar(char& ch)
{
	if( ScicRegs.SCIFFRX.bit.RXFFST == 0 ) return false; // no data in FIFIO
	ch = ScicRegs.SCIRXBUF.all;
	
	return true;
}

Uint32 UARTDriverC::ReadData(char* buffer)
{
	int i = 0;
	bool haveMore = ReadChar(buffer[i]);

	while(haveMore)
	{
		i++;
		haveMore = ReadChar(buffer[i]);
	}
	
	return i;
}

Uint32 UARTDriverC::GetData(char* buffer)
{
	int size = 0;
	
	DINT;
	ReadProcess(); // flush data
	while(m_Buffer.size() > 0 )
	{
		char ch = m_Buffer.front();
		*buffer = ch;
		buffer++;
		size++;
		m_Buffer.pop_front(); // remove
	}
	EINT;
	
	return size;
}

void UARTDriverC::ReadProcess()
{
	while( ScicRegs.SCIFFRX.bit.RXFFST > 0 ) // have new data
	{
		char ch = ScicRegs.SCIRXBUF.all;	 // Read data
		if( m_Buffer.size() < 500 ) m_Buffer.push_back(ch);
	}
}
